#include <iostream>
#include "Mutex.hpp"
#include <vector>
#include "Sem.hpp"

namespace RingBufferModule
{
    using namespace LockModule;
    using namespace SemModule;

    template <typename T>
    class RingBuffer
    {
    public:
        RingBuffer(int cap)
            : _ring(cap),
              _cap(cap),
              _p_step(0),
              _c_step(0),
              _datasem(0),
              _spacesem(cap)
        {
        }
        void Enqueue(const T &in)
        {
            _spacesem.P();

            {
                LockGuard lck(_plock);
                _ring[_p_step] = in;
                _p_step++;
                _p_step %= _cap;
            }

            _datasem.V();//通知消费者，我这里有数据了
        }
        void pop(T* out)
        {
            _datasem.P();

            {
                LockGuard lck(_plock);
                *out = _ring[_c_step];
                _c_step++;
                _c_step %= _cap;
            }

            _spacesem.V();
        }
        ~RingBuffer()
        {
        }

    private:
        std::vector<T> _ring;
        int _cap;
        int _p_step; // 生产者位置
        int _c_step; // 消费者位置

        Sem _datasem;  // 数据信号量
        Sem _spacesem; // 空间信号量

        Mutex _plock;
        Mutex _clock;
    };
}